package com.lcp.se.service;

import com.lcp.se.entity.data.VideoCall;
import com.lcp.se.entity.result.Result;
import com.lcp.se.mapper.VideoCallMapper;
import com.lcp.se.util.ProjectConstants;
import com.tencentyun.TLSSigAPIv2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author lcp
 * @date 2020/8/12 21:38
 */
@Service
public class VideoCallService {
    private final Logger log = LoggerFactory.getLogger(AppletUserService.class);

    @Resource
    private VideoCallMapper videoCallMapper;

    @Resource
    private PushMessageService pushMessageService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private TLSSigAPIv2 api;

    @Value("${mini-program.room-id-key-redis}")
    private String roomIdKey;

    /**
     * 创建
     */
    public Result<Map<String, Object>> createCall(String openId) {
        String timeMillis = System.currentTimeMillis() + "";

        // 生成 roomId，使用时间戳的后九位（分布式，高并发环境会出问题，请实现 roomId 的统一集中发放）
        String time = System.currentTimeMillis() + "";
        String roomId = time.substring(time.length() - 9);
        if (roomId.startsWith("0")) {
            roomId = roomId.replaceFirst("0", "11");
        }
        log.info("生成 roomId：" + roomId);

        String callId = openId + ProjectConstants.SEPARATOR_AUTH + timeMillis;
        VideoCall videoCall = new VideoCall()
                .setId(callId)
                .setCreateTime(new Date())
                .setCreateUserOpenId(openId)
                .setRoomId(Long.parseLong(roomId));

        int i = videoCallMapper.insert(videoCall);
        if (i == 1) {
            redisTemplate.opsForSet().add(roomIdKey, callId);
            Map<String, Object> result = new HashMap<>();
            String userSig = api.genSig(openId, 7200);
            result.put("callId", callId);
            result.put("userSig", userSig);
            result.put("roomID", Long.parseLong(roomId));
            pushMessageService.pushVideoCallMsg(videoCall);
            return Result.success("创建成功", result);
        }
        return Result.failure("创建失败");
    }

    /**
     * 接受，多线程环境下从数据库判断会有幻读的风险，因此使用 Redis
     */
    public Result<Map<String, Object>> handleCall(String openId, String callId) {
        // 只有第一个到达的能接听成功
        Long remove = redisTemplate.opsForSet().remove(roomIdKey, callId);
        if (remove != null && remove != 1L) {
            return Result.failure("该求助已被他人接听");
        }
        int i = videoCallMapper.updateById(
                new VideoCall().setId(callId).setHandleUserOpenId(openId).setHandleTime(new Date()));
        if (i == 1) {
            Map<String, Object> result = new HashMap<>();
            String userSig = api.genSig(openId, 7200);
            result.put("userSig", userSig);
            return Result.success("接听成功", result);
        }
        return Result.failure("接听失败");
    }

    /**
     * 结束
     */
    public Result<Map<String, Object>> endCall(String callId) {
        // 通话没被人接听的情况
        redisTemplate.opsForSet().remove(roomIdKey, callId);
        VideoCall call = videoCallMapper.selectById(callId);
        if (call.getEndTime() == null) {
            if (videoCallMapper.updateById(new VideoCall().setId(callId).setEndTime(new Date())) == 1) {
                return Result.success("更新通话为结束状态成功");
            } else {
                return Result.failure("更新通话为结束状态失败");
            }
        }
        return Result.failure("通话已结束");
    }

    /**
     * 生成 userSig 和 roomID 并返回，roomID 取值范围（1 - 4294967295），使用时间戳的话房间号27小时重复一次
     */
    public Map<String, Object> getUserSig(String openId, Integer userType) {
        Map<String, Object> result = new HashMap<>();
        // 调用 API 生成 userSIg
        String userSig = api.genSig(openId, 7200);
        result.put("userSig", userSig);
        if (userType == 0) {
            // 生成 roomID，使用时间戳的后九位（分布式，高并发环境会出问题，请实现 roomID 的统一集中发放）
            String time = System.currentTimeMillis() + "";
            String roomID = time.substring(time.length() - 9);
            if (roomID.startsWith("0")) {
                roomID = roomID.replaceFirst("0", "11");
            }
            log.info("生成 roomID：" + roomID);
            result.put("roomID", Long.parseLong(roomID));
        }
        return result;
    }
}
